<!-- 选择实体标签和关系标签 -->
<template>
  <div class="select-entity-and-relation-label">
    <div class="select-entity-and-relation-label-wrap" @click.stop="">
      <ul class="entity-and-relation-label-list-wrap my-scrollbar">
        <li
          v-for="item in labelOptions"
          :key="item.value"
          :class="[item.value === labelType && 'active']"
          @click.stop="changeLabelType(item)"
        >
          <p :title="item.title">{{ item.title }}</p>
          <i class="iconfont icon-arrow-right-s-line"></i>
        </li>
      </ul>

      <!-- 关系标签 -->
      <div v-if="labelType === 'Relation'" class="select-entity-and-relation-label-wrap">
        <ul v-if="relationSecondLevelLabelList.length" class="entity-and-relation-label-list-wrap relation w-200 my-scrollbar">
          <li
            v-for="(item, index) in relationSecondLevelLabelList"
            :key="item.onlyId"
            :class="[index === selectedSecondLevelIndex && 'active']"
            @click.stop="handleRelationParentChange(item, index)"
            @mouseenter="mouseenter(item)"
            @mouseleave="mouseleave(item)"
          >
            <div class="entity-and-relation-tag-wrap">
              <dmp-label :show-remove-button="false" :color="item.labelColor" :title="item.labelName" />
            </div>
            <p :title="item.text">{{ item.text }}</p>
            <div class="ml-auto">
              <i class="iconfont icon-arrow-right-s-line"></i>
            </div>
          </li>
        </ul>
        <default-image v-else height="100px" title="暂无内容" />
        <ul v-if="relationThreeLevelLabelList.length" class="entity-and-relation-label-list-wrap relation w160 my-scrollbar">
          <li v-for="item in relationThreeLevelLabelList" :key="item.id" @click.stop="handleRelationChange(item)">
            <p :title="item.name">{{ item.name }}</p>
          </li>
        </ul>
      </div>

      <!-- 实体标签 -->
      <ul v-else class="entity-and-relation-label-list-wrap entity my-scrollbar">
        <li v-for="item in entityLabelList" :key="item.id" @click.stop="handleEntityChange(item)">
          <p :title="item?.name">{{ item?.name }}</p>
        </li>
      </ul>
    </div>
  </div>
</template>

<script setup lang="ts">
  import { ref } from 'vue'
  import { useRequest } from 'vue-request'

  import { textLabelTagApi } from '@/services/index'
  import { hexToRgb } from '@/utils'

  import { EntityLabelLocationInfo } from '../dmp-text/utils/dmp-text/config'
  import DmpLabel from './DmpLabel.vue'
  import { MarkTaskLabelRes } from './LabelCard/types'

  export interface SelectEntityAndRelationLabelProps {
    labelType?: LabelType
    entityLabel?: EntityLabelLocationInfo
    entityLabelList?: EntityLabelLocationInfo[]
    taskId?: string
  }

  export type LabelType = 'Entity' | 'Relation'

  export interface LabelOptions {
    title: string
    value: LabelType
  }

  const props = withDefaults(defineProps<SelectEntityAndRelationLabelProps>(), {
    labelType: 'Entity'
  })

  const emits = defineEmits<{
    (event: 'entityChange', data: any): void
    (event: 'relationChange', startLabel: EntityLabelLocationInfo, endLabel: EntityLabelLocationInfo, relLabel: MarkTaskLabelRes): void
    (event: 'relationParentChange', data: any): void
  }>()

  const labelOptions: LabelOptions[] = [
    {
      title: '修改实体标签',
      value: 'Entity'
    },
    {
      title: '关联终止标签',
      value: 'Relation'
    }
  ]
  const labelType = ref<LabelType>(props.labelType || labelOptions[0].value)
  const changeLabelType = (item: any) => {
    labelType.value = item.value
    if (item.value === 'Entity') {
      relationThreeLevelLabelList.value = []
      selectedSecondLevelIndex.value = -1
    }
  }

  // 改变关系标签父级
  const selectedSecondLevelIndex = ref(-1)
  const handleRelationParentChange = (item: EntityLabelLocationInfo, index: number) => {
    selectedSecondLevelIndex.value = index
    getRelationThreeLevelLabelList(item)
    emits('relationParentChange', item)
  }

  // 改变关系标签
  const handleRelationChange = (item: MarkTaskLabelRes) => {
    const startLabel = props.entityLabel || {}
    const endLabel = relationSecondLevelLabelList.value[selectedSecondLevelIndex.value]

    emits('relationChange', startLabel, endLabel, item)
  }

  // 改变实体标签
  const handleEntityChange = (item: any) => {
    emits('entityChange', item)
  }

  // 实体标签
  const entityLabelList = ref<MarkTaskLabelRes[]>([])
  const { runAsync: runGetEntityLabelList } = useRequest(textLabelTagApi.entityList)
  const getEntityLabelList = async (params?: any) => {
    const res: any = await runGetEntityLabelList({
      taskId: props.taskId,
      ...params
    })
    entityLabelList.value = res.data
  }
  getEntityLabelList()

  // 关系标签
  const relationLabelList = ref<MarkTaskLabelRes[]>([])
  const { runAsync: runGetRelationLabelList } = useRequest(textLabelTagApi.relationList)
  const getRelationLabelList = async (params?: any) => {
    const res: any = await runGetRelationLabelList({
      taskId: props.taskId,
      ...params
    })
    relationLabelList.value = res.data
    getRelationSecondLevelLabelList()
  }
  getRelationLabelList()

  // 处理关联标签二级数据
  const relationSecondLevelLabelList = ref<EntityLabelLocationInfo[]>([])
  const getRelationSecondLevelLabelList = () => {
    const entityLabel = props.entityLabel
    const entityLabelList = props.entityLabelList

    // 筛选出当前实体标签的关联标签
    const filtrateAssociatedTag = relationLabelList.value.filter((item: any) => {
      return item.beginLabelId === entityLabel?.labelId
    })

    // 基于筛选的关联标签继续筛选出已标注在文本中的关联标签
    relationSecondLevelLabelList.value = entityLabelList?.filter((entityItem: any) => {
      return filtrateAssociatedTag?.some((item: any) => entityItem.labelId === item.endLabelId)
    }) as EntityLabelLocationInfo[]
  }

  // 获取关联标签三级数据
  const relationThreeLevelLabelList = ref<MarkTaskLabelRes[]>([])
  const getRelationThreeLevelLabelList = (item: EntityLabelLocationInfo) => {
    const entityLabel = props.entityLabel
    relationThreeLevelLabelList.value = relationLabelList.value.filter((relationItem: any) => {
      return relationItem.beginLabelId === entityLabel?.labelId && item.labelId === relationItem.endLabelId
    })
  }

  // 鼠标移入
  const mouseenter = (item: EntityLabelLocationInfo) => {
    const dmpTextWrap = document.getElementById('dmp-text-wrap')
    // 根据属性查找
    const dmpText = dmpTextWrap?.querySelector(`[data-only-id="${item.onlyId}"]`)
    updateSpan(dmpText, (prevNode: any) => {
      prevNode.style.background = hexToRgb(item.labelColor, 0.1)
    })
  }

  // 鼠标移出
  const mouseleave = (item: EntityLabelLocationInfo) => {
    const dmpTextWrap = document.getElementById('dmp-text-wrap')
    // 根据属性查找
    const dmpText = dmpTextWrap?.querySelector(`[data-only-id="${item.onlyId}"]`)
    updateSpan(dmpText, (prevNode: any) => {
      prevNode.style.background = 'transparent'
    })
  }

  /**
   * 更新指定节点前span标签样式
   */
  const updateSpan = (node: any, func: Function) => {
    let prevNode = node?.previousElementSibling
    while (prevNode && prevNode.nodeName === 'SPAN' && prevNode?.getAttribute('data-selection') === 'true') {
      func(prevNode)
      prevNode = prevNode.previousElementSibling
    }
  }

  defineExpose({
    changeLabelType: (item: any) => {
      changeLabelType({ value: item })
    }
  })
</script>

<style lang="less" scoped>
  .select-entity-and-relation-label {
    width: fit-content;
    background: #fff;
    background: rgba(255, 255, 255, 0.85);
    border-radius: 4px;
    box-shadow: 0 1px 3px 0 rgba(37, 37, 45, 0.14), 0 2px 8px 0 rgba(37, 37, 45, 0.14);

    .select-entity-and-relation-label-wrap {
      display: flex;

      .entity-and-relation-label-list-wrap {
        overflow-y: auto;
        padding: 4px 0;
        width: 130px;
        max-height: 200px;
        border-right: 1px solid rgba(0, 0, 0, 0.13);

        &:last-child {
          border-right: none;
        }

        &.entity {
          width: 120px;
        }

        &.relation {
          width: 200px;

          &:last-child {
            width: 160px;
          }
        }

        > li {
          display: flex;
          justify-content: space-between;
          padding: 5px 12px;
          font-size: 14px;
          color: rgba(0, 0, 0, 0.85);
          font-weight: 400;
          line-height: 22px;
          gap: 0 4px;
          cursor: pointer;

          &.active,
          &:hover {
            background: rgba(245, 245, 245, 0.8);
            border-radius: 2px;
            font-weight: 700;
          }

          > p {
            .elliptical-1();
          }

          i {
            color: rgba(0, 0, 0, 0.45);
            font-weight: 400;
          }
        }

        .entity-and-relation-tag-wrap {
          margin-right: 4px;
          max-width: 84px;
          height: 24px;
          flex-shrink: 0;
        }
      }
    }
  }
</style>
